﻿using DBUtil.FastEntity.Annotations;
using DotNetCommon;
using DotNetCommon.Data;
using DotNetCommon.Extensions;
using DotNetCommon.Logger;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace DBUtil.FastEntity.Builders
{
    /// <summary>
    /// 插入构造器
    /// </summary>
    public class InsertBuilder<T> : Builder<T> where T : class, new()
    {
        protected static readonly ILogger<InsertBuilder<T>> logger = LoggerFactory.CreateLogger<InsertBuilder<T>>();
        public EnumInsertBuilderType Type { get; set; }

        #region 初始化
        public T[] Entities { get; set; }
        public InsertBuilder(EntityManager<T> entityManager, T[] entities) : base(entityManager)
        {
            Entities = entities;
            Type = EnumInsertBuilderType.EntityArray;
        }
        public InsertBuilder(EntityManager<T> entityManager, IEnumerable<T> entities) : base(entityManager)
        {
            Entities = entities.ToArray();
            Type = EnumInsertBuilderType.EntityArray;
        }

        public Expression<Func<T>> Expression { get; set; }
        public InsertBuilder(EntityManager<T> entityManager, Expression<Func<T>> expression) : base(entityManager)
        {
            Expression = expression;
            Type = EnumInsertBuilderType.Expression;
        }

        public object Dto { get; }
        public InsertBuilder(EntityManager<T> entityManager, object dto) : base(entityManager)
        {
            if (dto == null) throw new ArgumentNullException(nameof(dto));
            this.Dto = dto;
            Type = EnumInsertBuilderType.Dto;
        }
        #endregion
        #region 超时设置
        private int? _timeoutSeconds { get; set; }
        public int? TimeoutSeconds => _timeoutSeconds;
        public virtual InsertBuilder<T> CommandTimeout(int timeoutSeconds)
        {
            _timeoutSeconds = timeoutSeconds;
            return this;
        }
        #endregion
        #region ConfigEntitys
        public List<Action<EntityInfo>> ConfigInsertEntitys { get; set; } = new List<Action<EntityInfo>>();
        public InsertBuilder<T> ConfigInsertEntity(Action<EntityInfo> action)
        {
            ConfigInsertEntitys.Add(action);
            return this;
        }
        public List<Action<EntityInfo>> ConfigSelectEntitys { get; set; } = new List<Action<EntityInfo>>();
        public InsertBuilder<T> ConfigSelectEntity(Action<EntityInfo> action)
        {
            ConfigSelectEntitys.Add(action);
            return this;
        }
        #endregion
        #region GetComputeEntity
        protected EntityInfo GetComputeSelectEntity()
        {
            var res = entityManager.EntityInfo.Clone();
            foreach (var act in ConfigSelectEntitys)
            {
                act?.Invoke(res);
            }
            res.EntityPropertyInfos = res.EntityPropertyInfos.Where(i => i.IsColumn && !i.IsIgnoreSelect).ToList();
            return res;
        }

        protected EntityInfo GetComputeInsertEntity()
        {
            var res = entityManager.EntityInfo.Clone();
            foreach (var act in ConfigInsertEntitys)
            {
                act?.Invoke(res);
            }
            res.EntityPropertyInfos = res.EntityPropertyInfos.Where(i => i.IsColumn && !i.IsIgnoreInsert).ToList();
            return res;
        }
        #endregion

        public virtual TReturn RunInMonitor<TReturn>(Func<string> generateSql, Func<string, TReturn> func)
        {
            Stopwatch st = null;
            string sql = string.Empty;
            TReturn res = default;
            if (IsCurdBefore)
            {
                st = new Stopwatch();
                st.Start();
                try
                {
                    sql = generateSql();
                    st.Stop();
                    var arg = new EntityCurdBeforeArgument
                    {
                        Sql = sql,
                        TimeSpan = st.Elapsed
                    };
                    BeforeActions.ForEach(act => act?.Invoke(arg));
                }
                finally
                {
                    if (st.IsRunning) st.Stop();
                }
            }
            else
            {
                sql = generateSql();
            }
            if (IsCurdAfter)
            {
                st = st ?? new Stopwatch();
                st.Start();
                try
                {
                    res = func(sql);
                    st.Stop();
                    var arg2 = new EntityCurdAfterArgument
                    {
                        Sql = sql,
                        TimeSpan = st.Elapsed
                    };
                    AfterActions.ForEach(act => act?.Invoke(arg2));
                }
                finally
                {
                    if (st.IsRunning) st.Stop();
                }
            }
            else
            {
                res = func(sql);
            }
            return res;
        }

        #region 执行
        /// <summary>
        /// 插入并返回Id
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <returns></returns>
        public virtual TKey ExecuteGetId<TKey>()
            => RunInMonitor(() => ToSql(EnumInsertToSql.ExecuteGetId), sql => db.SelectScalar<TKey>(sql, CommandType.Text, TimeoutSeconds));

        /// <summary>
        /// 插入并返回Id
        /// </summary>
        /// <returns></returns>
        public virtual int ExecuteGetId() => ExecuteGetId<int>();

        /// <summary>
        /// 插入并返回Id
        /// </summary>
        /// <returns></returns>
        public virtual long ExecuteGetIdLong() => ExecuteGetId<long>();

        /// <summary>
        /// 插入并返回受影响的行数
        /// </summary>
        /// <returns></returns>
        public virtual int ExecuteAffrows()
            => RunInMonitor(() => ToSql(EnumInsertToSql.ExecuteAffrow), sql => db.ExecuteSql(sql, CommandType.Text, TimeoutSeconds));

        /// <summary>
        /// 插入并返回实体
        /// </summary>
        /// <returns></returns>
        public virtual T ExecuteInserted()
            => RunInMonitor(() => ToSql(EnumInsertToSql.ExecuteInserted), sql => db.SelectModel<T>(sql, CommandType.Text, TimeoutSeconds));

        /// <summary>
        /// 插入并返回实体集合
        /// </summary>
        /// <returns></returns>
        public virtual List<T> ExecuteInsertedList()
            => RunInMonitor(() => ToSql(EnumInsertToSql.ExecuteInserteds), sql => db.SelectModelList<T>(sql, CommandType.Text, TimeoutSeconds));
        #endregion

        //便于 BulkCopy
        public DataTable ToDataTable()
        {
            var (Models, entityInfo) = ComputeModels();
            var primary = entityInfo.PrimaryKeyColumn;

            //所有行的主键值,后续可能用到
            object[] keyVals = new object[Models.Length];
            //是否是数据库生成的主键
            bool isDbCreate = false;
            //NewId: 是否需要重设id
            bool needResetId = false;
            //NewId: 是否需要生成id
            bool needGenerate = false;

            var dt = new DataTable(entityInfo.FullName);
            int autoCount = 0;
            int customCount = 0;

            //先处理主键
            if (primary != null)
            {
                switch (primary.PrimaryKeyStrategy)
                {
                    case KeyStrategy.Guid:
                        //允许手动插入和自动生成
                        dt.Columns.Add(primary.ColumnName);
                        for (var i = 0; i < Models.Length; i++)
                        {
                            var Model = Models[i];
                            var keyVal = primary.PropertyInfo.GetValue(Model);
                            if (keyVal == null || Equals(keyVal, primary.DefaultValue)) keyVal = Guid.NewGuid().ToString();
                            keyVals[i] = keyVal;
                        }
                        break;
                    case KeyStrategy.NewId:
                    case KeyStrategy.Sequence://mysql不支持序列
                        //允许手动插入和自动生成
                        logger.LogWarning($"mysql不支持序列,针对[类型: {entityInfo.TypeFullName}]的配置(KeyStrategy.Sequence),使用(KeyStrategy.NewId)替换.");
                        dt.Columns.Add(primary.ColumnName);
                        for (var i = 0; i < Models.Length; i++)
                        {
                            var Model = Models[i];
                            var keyVal = primary.PropertyInfo.GetValue(Model);
                            if (keyVal == null || Equals(keyVal, primary.DefaultValue))
                            {
                                autoCount++;
                            }
                            else
                            {
                                customCount++;
                                keyVals[i] = keyVal;
                            }
                            if (autoCount > 0 && customCount > 0) throw new Exception($"对于主键策略为[KeyStrategy.Sequence]或[KeyStrategy.NewId]的,批量插入时只能全部由 DBUtil 生成或者全部自行指定!");
                        }
                        if (autoCount > 0)
                        {
                            //自动生成
                            needGenerate = true;
                        }
                        else
                        {
                            //用户指定,需要重设id
                            needResetId = true;
                        }
                        break;
                    case KeyStrategy.Identity:
                        //mysql 也允许插入自增列
                        for (var i = 0; i < Models.Length; i++)
                        {
                            var Model = Models[i];
                            var keyVal = primary.PropertyInfo.GetValue(Model);
                            if (keyVal == null || Equals(keyVal, primary.DefaultValue))
                            {
                                autoCount++;
                            }
                            else
                            {
                                customCount++;
                                keyVals[i] = keyVal;
                            }
                            if (autoCount > 0 && customCount > 0) throw new Exception($"对于主键策略为[KeyStrategy.Identity]的,批量插入时只能全部由数据库生成或者全部自行指定!");
                        }
                        if (customCount > 0)
                        {
                            dt.Columns.Add(primary.ColumnName);
                        }
                        else
                        {
                            isDbCreate = true;
                        }
                        break;
                    case KeyStrategy.Custom:
                        dt.Columns.Add(primary.ColumnName);
                        for (var i = 0; i < Models.Length; i++)
                        {
                            var Model = Models[i];
                            var keyVal = primary.PropertyInfo.GetValue(Model);
                            keyVals[i] = keyVal;
                        }
                        break;
                    case KeyStrategy.CustomGenerator:
                        dt.Columns.Add(primary.ColumnName);
                        for (var i = 0; i < Models.Length; i++)
                        {
                            var Model = Models[i];
                            var keyVal = primary.EntityIdGenerator.Generator(new EntityIdGeneratorContext
                            {
                                db = db,
                                EntityInfo = entityInfo,
                                Data = Model,
                                PrimaryKeyInfo = primary
                            });
                            keyVals[i] = keyVal;
                        }
                        break;
                }
            }

            //表数据 非主键
            var now = string.Empty;
            string userId = null;
            if (entityInfo.IsAudit)
            {
                now = entityManager.GetNow();
                userId = entityManager.GetUserId();
            }

            for (var p = 0; p < Models.Length; p++)
            {
                var Model = Models[p];
                var row = dt.NewRow();
                dt.Rows.Add(row);
                //Normal 列
                for (int i = 0; i < entityInfo.NormalColumns.Count; i++)
                {
                    var col = entityInfo.NormalColumns[i];

                    object val = null;

                    if (p == 0) dt.Columns.Add(col.ColumnName);
                    //json
                    val = col.PropertyInfo.GetValue(Model);
                    if (col.IsStoreJsonFast)
                    {
                        var json = val?.ToJsonFast(dateFormatString: col.StoreJsonFastDateFormatString
                            , isLongToString: col.StoreJsonFastIsLongToString
                            , IgnoreNull: col.StoreJsonFastIgnoreNull
                            , enum2String: col.StoreJsonFastEnum2String
                            , lowerCamelCase: col.StoreJsonFastLowerCamelCase
                            , isIntend: col.StoreJsonFastIsIntend
                            , isAllToString: col.StoreJsonFastIsAllToString
                            , allNumDigit: col.StoreJsonFastAllNumDigit
                            , decimalDigit: col.StoreJsonFastDecimalDigit);
                        row[col.ColumnName] = json;
                        continue;
                    }
                    if (col.IsStoreJson)
                    {
                        var json = val?.ToJson();
                        row[col.ColumnName] = json;
                        continue;
                    }

                    row[col.ColumnName] = val;
                }
                //Audit 列
                for (int i = 0; i < entityInfo.AuditColumns.Count; i++)
                {
                    var col = entityInfo.AuditColumns[i];
                    //create
                    if (col.IsAuditCreateTime)
                    {
                        if (p == 0) dt.Columns.Add(col.ColumnName);
                        row[col.ColumnName] = now;
                        continue;
                    }
                    if (col.IsAuditCreateUserId)
                    {
                        if (p == 0) dt.Columns.Add(col.ColumnName);
                        row[col.ColumnName] = userId == "null" ? col.AuditDefaultValue : DBNull.Value;
                        continue;
                    }
                    //update
                    if (col.IsAuditUpdateTime && col.IsAuditInitUseCreateValue)
                    {
                        if (p == 0) dt.Columns.Add(col.ColumnName);
                        row[col.ColumnName] = now;
                        continue;
                    }
                    if (col.IsAuditUpdateUserId && col.IsAuditInitUseCreateValue)
                    {
                        if (p == 0) dt.Columns.Add(col.ColumnName);
                        row[col.ColumnName] = userId == "null" ? col.AuditDefaultValue : DBNull.Value;
                        continue;
                    }
                    //delete
                    continue;
                }
            }

            if (needResetId)
            {
                //声明 newId 模式,但又指定了主键值 插入前需要先占用可能重复的id
                var currentId = db.GetCurrentId(entityInfo.FullName, primary.ColumnName);
                var customMax = keyVals.Select(i => Convert.ToInt64(i)).Max();
                if (currentId > 0 && currentId < customMax)
                {
                    db.NewIds(entityInfo.FullName, primary.ColumnName, (int)(customMax - currentId));
                }
            }
            else if (needGenerate)
            {
                //声明 NewId 模式,需要批量生成
                var ids = db.NewIds(entityInfo.FullName, primary.ColumnName, autoCount);
                for (int m = 0; m < ids.Count; m++)
                {
                    keyVals[m] = ids[m];
                }
            }

            //主键
            if (!isDbCreate)
            {
                for (int i = 0; i < Models.Length; i++)
                {
                    dt.Rows[i][0] = keyVals[i];
                }
            }
            return dt;
        }

        public (T[] Models, EntityInfo entityInfo) ComputeModels()
        {
            if (Type == EnumInsertBuilderType.EntityArray && Entities.Length == 0) throw new Exception("必须指定要插入的实体数据!");
            if (Type == EnumInsertBuilderType.Expression && Expression == null) throw new Exception("必须指定要插入的表达式!");
            if (Type == EnumInsertBuilderType.Dto && Dto == null) throw new Exception("必须指定要插入的dto!");

            var info = GetComputeInsertEntity();

            T[] Models = null;
            if (Type == EnumInsertBuilderType.EntityArray)
            {
                Models = Entities;
            }
            else if (Type == EnumInsertBuilderType.Expression)
            {
                var names = ExpressionHelper.GetInitOrReturnPropNames(Expression);
                var tmp = ExpressionHelper.ReduceLambda(Expression);
                var model = (tmp as ConstantExpression).Value as T;
                Models = new[] { model };
                //移除非Expression包含的属性
                info.RemoveAllNormalColumnsExcept(names.ToArray());
            }
            else if (Type == EnumInsertBuilderType.Dto)
            {
                var type = Dto.GetType();
                Type dtoType = null;
                if (type.Implements<IEnumerable>())
                {
                    dtoType = type.IsArray ? type.GetElementType() : type.GetGenericArguments()[0];
                    Models = Dto.Mapper<T[]>();
                }
                else
                {
                    dtoType = type;
                    Models = new[] { Dto.Mapper<T>() };
                }
                //移除非Dto包含的属性(除了审计外)
                var names = dtoType.GetProperties().Select(i => i.Name);
                info.RemoveAllNormalColumnsExcept(names.ToArray());
            }
            return (Models, info);
        }

        /// <summary>
        /// 返回生成的sql
        /// </summary>
        public string ToSql(EnumInsertToSql enumInsertToSql = EnumInsertToSql.ExecuteAffrow)
        {
            var (Models, entityInfo) = ComputeModels();

            var primary = entityInfo.PrimaryKeyColumn;
            if (primary == null && enumInsertToSql == EnumInsertToSql.ExecuteGetId)
                throw new Exception($"当前Entity({entityInfo.TypeFullName})未定义主键,无法获取插入后的主键值!");
            if (primary == null && (enumInsertToSql == EnumInsertToSql.ExecuteInserted || enumInsertToSql == EnumInsertToSql.ExecuteInserteds))
                throw new Exception($"当前Entity({entityInfo.TypeFullName})未定义主键(MySql),无法查询插入后的数据!");

            var sbInsertColumns = new List<string>();
            var sbInsertValues = new List<List<string>>(Models.Length);
            Models.ForEach(i => sbInsertValues.Add(new List<string>()));

            //所有行的主键值,后续可能用到
            object[] keyVals = new object[Models.Length];
            //是否是数据库生成的主键
            bool isDbCreate = false;
            //NewId: 是否需要重设id
            bool needResetId = false;
            //NewId: 是否需要生成id
            bool needGenerate = false;

            //用于识别多行数据的主键不能部分指定值而部分自动生成
            int customCount = 0;
            int autoCount = 0;

            //先处理主键
            if (primary != null)
            {
                if (primary.PrimaryKeyStrategy == KeyStrategy.NewId || (primary.PrimaryKeyStrategy == KeyStrategy.Sequence && !db.IsSupportSequence()))
                {
                    //当做 NewId 处理
                    logger.LogWarning($"mysql不支持序列,针对[类型: {entityInfo.TypeFullName}]的配置(KeyStrategy.Sequence),使用(KeyStrategy.NewId)替换.");
                    sbInsertColumns.Add(primary.ColumnName);
                    for (var i = 0; i < Models.Length; i++)
                    {
                        var Model = Models[i];
                        var keyVal = primary.PropertyInfo.GetValue(Model);
                        if (keyVal == null || Equals(keyVal, primary.DefaultValue))
                        {
                            autoCount++;
                        }
                        else
                        {
                            customCount++;
                            keyVals[i] = keyVal;
                            sbInsertValues[i].Add($"'{keyVal}'");
                        }
                        if (autoCount > 0 && customCount > 0) throw new Exception($"对于主键策略为[KeyStrategy.Sequence]或[KeyStrategy.NewId]的,批量插入时只能全部由 DBUtil 生成或者全部自行指定!");
                    }
                    if (autoCount > 0)
                    {
                        //自动生成
                        needGenerate = true;
                    }
                    else
                    {
                        //用户指定,需要重设id
                        needResetId = true;
                    }
                }
                else if (primary.PrimaryKeyStrategy == KeyStrategy.Guid)
                {
                    //允许手动插入和自动生成
                    sbInsertColumns.Add(primary.ColumnName);
                    for (var i = 0; i < Models.Length; i++)
                    {
                        var Model = Models[i];
                        var keyVal = primary.PropertyInfo.GetValue(Model);
                        if (keyVal == null || Equals(keyVal, primary.DefaultValue)) keyVal = Guid.NewGuid().ToString();
                        keyVals[i] = keyVal;
                        sbInsertValues[i].Add($"'{keyVal}'");
                    }
                }
                else if (primary.PrimaryKeyStrategy == KeyStrategy.Identity)
                {
                    for (var i = 0; i < Models.Length; i++)
                    {
                        var Model = Models[i];
                        var keyVal = primary.PropertyInfo.GetValue(Model);
                        if (keyVal == null || Equals(keyVal, primary.DefaultValue))
                        {
                            autoCount++;
                        }
                        else
                        {
                            customCount++;
                            keyVals[i] = keyVal;
                        }
                        if (autoCount > 0 && customCount > 0) throw new Exception($"对于主键策略为[KeyStrategy.Identity]的,批量插入时只能全部由数据库生成或者全部自行指定!");
                    }
                    if (customCount > 0)
                    {
                        sbInsertColumns.Add(primary.ColumnName);
                        for (int m = 0; m < keyVals.Length; m++)
                        {
                            sbInsertValues[m].Add(keyVals[m].ToString());
                        }
                    }
                    else
                    {
                        isDbCreate = true;
                    }
                }
                else if (primary.PrimaryKeyStrategy == KeyStrategy.Custom)
                {
                    sbInsertColumns.Add(primary.ColumnName);
                    for (var i = 0; i < Models.Length; i++)
                    {
                        var Model = Models[i];
                        var keyVal = primary.PropertyInfo.GetValue(Model);
                        keyVals[i] = keyVal;
                        sbInsertValues[i].Add(db.ConvertToSqlSegment(keyVal).UnWrap());
                    }
                }
                else if (primary.PrimaryKeyStrategy == KeyStrategy.CustomGenerator)
                {
                    sbInsertColumns.Add(primary.ColumnName);
                    for (var i = 0; i < Models.Length; i++)
                    {
                        var Model = Models[i];
                        var keyVal = primary.EntityIdGenerator.Generator(new EntityIdGeneratorContext
                        {
                            db = db,
                            EntityInfo = entityInfo,
                            Data = Model,
                            PrimaryKeyInfo = primary
                        });
                        keyVals[i] = keyVal;
                        sbInsertValues[i].Add(db.ConvertToSqlSegment(keyVal).UnWrap());
                    }
                }
                else if (primary.PrimaryKeyStrategy == KeyStrategy.Sequence && db.IsSupportSequence())
                {
                    //序列
                    //TODO
                }
                else
                {
                    throw new Exception($"不支持的主键策略:{primary.PrimaryKeyStrategy}.");
                }
            }

            var now = string.Empty;
            string userId = null;
            if (entityInfo.IsAudit)
            {
                now = entityManager.GetNow();
                userId = entityManager.GetUserId();
            }

            for (var p = 0; p < Models.Length; p++)
            {
                var Model = Models[p];
                //Normal 列
                for (int i = 0; i < entityInfo.NormalColumns.Count; i++)
                {
                    var col = entityInfo.NormalColumns[i];

                    object val = null;

                    if (p == 0) sbInsertColumns.Add(col.ColumnName);
                    val = col.PropertyInfo.GetValue(Model);
                    if (col.IsRawString)
                    {
                        sbInsertValues[p].Add(val.ToString());
                        continue;
                    }
                    //json
                    if (col.IsStoreJsonFast)
                    {
                        var json = val?.ToJsonFast(dateFormatString: col.StoreJsonFastDateFormatString
                            , isLongToString: col.StoreJsonFastIsLongToString
                            , IgnoreNull: col.StoreJsonFastIgnoreNull
                            , enum2String: col.StoreJsonFastEnum2String
                            , lowerCamelCase: col.StoreJsonFastLowerCamelCase
                            , isIntend: col.StoreJsonFastIsIntend
                            , isAllToString: col.StoreJsonFastIsAllToString
                            , allNumDigit: col.StoreJsonFastAllNumDigit
                            , decimalDigit: col.StoreJsonFastDecimalDigit);
                        sbInsertValues[p].Add(db.ConvertToSqlSegment(json).UnWrap());
                        continue;
                    }
                    if (col.IsStoreJson)
                    {
                        var json = val?.ToJson();
                        sbInsertValues[p].Add(db.ConvertToSqlSegment(json).UnWrap());
                        continue;
                    }
                    sbInsertValues[p].Add(db.ConvertToSqlSegment(val).UnWrap());
                }
                //Audit 列
                for (int i = 0; i < entityInfo.AuditColumns.Count; i++)
                {
                    var col = entityInfo.AuditColumns[i];

                    //create
                    if (col.IsAuditCreateTime)
                    {
                        if (p == 0) sbInsertColumns.Add(col.ColumnName);
                        sbInsertValues[p].Add(now);
                        continue;
                    }
                    if (col.IsAuditCreateUserId)
                    {
                        if (p == 0) sbInsertColumns.Add(col.ColumnName);
                        sbInsertValues[p].Add(userId == "null" ? db.ConvertToSqlSegment(col.AuditDefaultValue).Data : userId);
                        continue;
                    }
                    //update
                    if (col.IsAuditUpdateTime && col.IsAuditInitUseCreateValue)
                    {
                        if (p == 0) sbInsertColumns.Add(col.ColumnName);
                        sbInsertValues[p].Add(now);
                        continue;
                    }
                    if (col.IsAuditUpdateUserId && col.IsAuditInitUseCreateValue)
                    {
                        if (p == 0) sbInsertColumns.Add(col.ColumnName);
                        sbInsertValues[p].Add(userId == "null" ? db.ConvertToSqlSegment(col.AuditDefaultValue).Data : userId);
                        continue;
                    }
                    //delete
                    continue;
                }
            }

            if (needResetId)
            {
                //声明 newId 模式,但又指定了主键值 插入前需要先占用可能重复的id
                var currentId = db.GetCurrentId(entityInfo.FullName, primary.ColumnName);
                var customMax = keyVals.Select(i => Convert.ToInt64(i)).Max();
                if (currentId > 0 && currentId < customMax)
                {
                    db.NewIds(entityInfo.FullName, primary.ColumnName, (int)(customMax - currentId));
                }
            }
            else if (needGenerate)
            {
                //声明 NewId 模式,需要批量生成
                var ids = db.NewIds(entityInfo.FullName, primary.ColumnName, autoCount);
                for (int m = 0; m < ids.Count; m++)
                {
                    keyVals[m] = ids[m];
                    sbInsertValues[m].Insert(0, ids[m].ToString());
                }
            }

            var insertValues = sbInsertValues.Select(i => $"({i.ToStringSeparated(",")})").ToStringSeparated(",\r\n\t");
            var sql = $"insert into {entityInfo.FullName}({sbInsertColumns.ToStringSeparated(",")}) values\r\n\t{insertValues};";
            switch (enumInsertToSql)
            {
                case EnumInsertToSql.ExecuteGetId:
                    if (isDbCreate)
                    {
                        // 需要数据库生成
                        sql += "\r\nselect LAST_INSERT_ID();";
                    }
                    else
                    {
                        sql += $"\r\nselect '{keyVals.LastOrDefault()}';";
                    }
                    break;
                case EnumInsertToSql.ExecuteAffrow:
                    break;
                case EnumInsertToSql.ExecuteInserted:
                case EnumInsertToSql.ExecuteInserteds:
                    var selectEntityInfo = GetComputeSelectEntity();
                    var segs = selectEntityInfo.EntityPropertyInfos.Select(i => i.ColumnName).ToStringSeparated(",");
                    if (isDbCreate == true)
                    {
                        // Identity
                        //一条insert语句(即使多个插入行),得到的也是第一条数据插入时的自增id
                        //多条insert语句,得到的是最后的
                        //var tmp = Interlocked.Increment(ref counter);
                        //var counterName = $"id_autogene_{tmp}";
                        if (enumInsertToSql == EnumInsertToSql.ExecuteInserted)
                        {
                            //获取最后一条                            
                            sql += $"\r\nselect {segs} from {selectEntityInfo.FullName} where {selectEntityInfo.PrimaryKeyColumn.ColumnName}=LAST_INSERT_ID();";
                        }
                        else
                        {
                            //获取所有插入的
                            sql += $"\r\nselect {segs} from {selectEntityInfo.FullName} where {selectEntityInfo.PrimaryKeyColumn.ColumnName}>=LAST_INSERT_ID() order by {selectEntityInfo.PrimaryKeyColumn.ColumnName}  limit {Models.Length};";
                        }
                    }
                    else
                    {
                        //非数据库生成  已经知道主键值
                        if (enumInsertToSql == EnumInsertToSql.ExecuteInserted)
                        {
                            //获取最后一条
                            sql += $"\r\nselect {segs} from {selectEntityInfo.FullName} where {selectEntityInfo.PrimaryKeyColumn.ColumnName} ={db.ConvertToSqlSegment(keyVals.LastOrDefault()).UnWrap()};";
                        }
                        else
                        {
                            //获取所有插入的
                            sql += $"\r\nselect {segs} from {selectEntityInfo.FullName} where {selectEntityInfo.PrimaryKeyColumn.ColumnName} in({keyVals.Select(i => $"'{i}'").ToStringSeparated(",")});";
                        }
                    }
                    break;
            }
            return sql;
        }
    }

    public enum EnumInsertToSql
    {
        ExecuteAffrow,
        ExecuteGetId,
        ExecuteInserted,
        ExecuteInserteds,
    }

    public enum EnumInsertBuilderType
    {
        EntityArray,
        Dto,
        Expression
    }
}